package com.work.controller;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.work.config.AuthConfig;
import com.work.common.event.WorkEvent;
import com.work.fn.GenerateCaptcha;
import com.work.service.UserClockService;
import com.work.service.UserLoginService;
import com.work.vo.UserLoginVO;
import com.work.vo.UserRegisterVO;
import com.work.common.base.WaterMarkImage;
import com.work.common.enums.UserRegisterType;
import com.work.common.result.Result;
import com.work.common.result.ResultType;
import com.work.common.util.AssertUtil;
import com.work.common.util.ImageUtil;
import com.work.common.util.JwsUtil;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.nio.file.Files;

@RestController
@RequestMapping("user")
@RequiredArgsConstructor
public class UserAuthController {

    private final AuthenticationManager authenticationManager;
    private final UserLoginService userLoginService;
    private final DefaultKaptcha kaptchaConfig;
    private final ApplicationContext applicationContextEvent;
    private final UserClockService userClockService;
    private final AuthConfig authConfig;

    @PostMapping("login")
    public Result<String> login(@Valid @RequestBody UserLoginVO userLoginVO,
                                HttpSession session) {

        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                userLoginVO.getUsername(),
                userLoginVO.getPassword()
        );

        final Long tokenExpireTime = authConfig.getJwtAuth().getAccessTokenExpire();
        JwsUtil.getToken(userLoginVO.getUsername(), tokenExpireTime);

        Authentication authenticate = authenticationManager.authenticate(token);

        SecurityContextHolder.getContext().setAuthentication(authenticate);

        session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());

        return Result.success(ResultType.LOGIN_SUCCESS, SecurityContextHolder.getContext().getAuthentication().getName());
    }

    @GetMapping("logout")
    public Result<String> logout(HttpSession session) {
        session.invalidate();
        return Result.success(ResultType.SUCCESS);
    }

    @PostMapping("register")
    public Result<Boolean> register(@Valid @RequestBody UserRegisterVO userRegisterVO) {
        try {
//            TODO 待实现验证码校验
            final boolean user = userLoginService.userExist(userRegisterVO.getUsername());
            AssertUtil.isFalse(user, UserRegisterType.ACCOUNT_EXIST.getMsg());
            final boolean register = userLoginService.register(userRegisterVO);
            return Result.success(ResultType.SUCCESS, register);
        } catch (Exception e) {
            final UserRegisterType accountNotExist = UserRegisterType.ACCOUNT_EXIST;
            return Result.fail(
                    accountNotExist.getCode(),
                    accountNotExist.getMsg());
        }
    }

    @GetMapping("code")
    public void generateCaptcha(HttpServletResponse response) throws IOException {
        GenerateCaptcha.generate(() -> kaptchaConfig.createImage(kaptchaConfig.createText()), response);
    }

    @PostMapping("clock")
    public Result<String> userClock() {
        return Result.success(ResultType.SUCCESS);
    }

    @GetMapping("text")
    public void generateText(HttpServletResponse response) throws IOException {
        final OutputStream outputStream = ImageUtil.addTextWatermark(new WaterMarkImage()
                .setText("我靠呀")
                .setInput(Files.newInputStream(new File("E:\\idea\\free\\fa.png").toPath())));
        final ByteArrayOutputStream stream = (ByteArrayOutputStream) outputStream;
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType(MediaType.IMAGE_PNG_VALUE);
        applicationContextEvent.publishEvent(new WorkEvent(this));
        try {
            assert outputStream != null;
            response.getOutputStream().write(stream.toByteArray());
            response.getOutputStream().flush();
        } catch (IOException e) {
            response.sendError(500, "服务器异常");
        }
    }

}
